package ligne2vie.topos.client.panels;

import java.util.List;

import ligne2vie.topos.client.maps.MyMapWidget;
import ligne2vie.topos.shared.bo.TMapPoint;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;

/**
 * The class {@link GeoSearchResultDisplayPanel} allows displaying several geo results, allowing users to quickly center
 * the map on the result.
 * 
 * @author thuguerre
 * @since 1.1.0
 */
public class GeoSearchResultDisplayPanel extends AbsolutePanel {

	/**
	 * Table of 2 columns displaying all results. Number of lines = number of results. First column displays marker
	 * icon. Second column display marker description.
	 */
	private FlexTable resultTable = new FlexTable();

	/**
	 * Message panel used to display a message to the user if results are not valid.
	 */
	private HTML messagePanel = new HTML();

	/**
	 * Default constructor.
	 */
	public GeoSearchResultDisplayPanel() {

		this.add(resultTable, 0, 0);
		this.add(messagePanel, 0, 0);
	}

	/**
	 * The method {@link #displayPoints(List)} clears and then fills the inner table displaying all received geo
	 * results.
	 * 
	 * @param results
	 *            Geo Results to display.
	 */
	public void displayPoints(List<TMapPoint> results) {

		clear();

		if (results.size() == 0) {

			messagePanel.setHTML("Aucun r&eacute;sultat n'a &eacute;t&eacute trouv&eacute;.");

		} else if (results.size() > MyMapWidget.MAX_SEARCH_GEO_RESULTS) {

			messagePanel.setHTML("Trop de r&eacute;sultats. Affinez votre demande.");

		} else if (results.size() == 1) {

			resultTable.setWidget(0, 0, new ResultImage(results.get(0)));
			resultTable.setWidget(0, 1, new ResultDescription(results.get(0)));

		} else {

			int index = 0;
			for (TMapPoint result : results) {

				resultTable.setWidget(index, 0, new ResultImage(result));
				resultTable.setWidget(index, 1, new ResultDescription(result));

				index++;
			}
		}

		messagePanel.setVisible(results.size() == 0 || results.size() > MyMapWidget.MAX_SEARCH_GEO_RESULTS);
		resultTable.setVisible(results.size() > 0 && results.size() <= MyMapWidget.MAX_SEARCH_GEO_RESULTS);

		this.setHeight(Math.max(messagePanel.getOffsetHeight(), resultTable.getOffsetHeight()) + "px");
	}

	/**
	 * The method {@link #clear()} removes all results.
	 */
	public void clear() {

		// TODO should be called when all results are clean from map = specific event ?

		resultTable.removeAllRows();
	}

	/**
	 * The class {@link ResultImage} allows displaying an image using the marker icon used to display the result on the
	 * map. When clicking on this image, the map is automatically centered on the result.
	 * 
	 * @author thuguerre
	 * @since 1.1.0
	 */
	private class ResultImage extends Image {

		/**
		 * Default constructor.
		 * 
		 * @param result
		 *            Georesult which should be displayed as an image.
		 */
		public ResultImage(TMapPoint result) {

			super(result.getIconPath());
			this.addClickHandler(new MapCenterOnResult(result));
			this.addStyleDependentName("clickable");
		}
	}

	/**
	 * The class {@link ResultDescription} allows displaying the description of the georesult. When clicking on this
	 * description, the map is automatically centered on the result.
	 * 
	 * @author thuguerre
	 * @since 1.1.0
	 */
	private class ResultDescription extends HTML {

		/**
		 * Default constructor.
		 * 
		 * @param result
		 *            Georesult for which displaying the description.
		 */
		public ResultDescription(TMapPoint result) {

			super(result.getShortDescription());
			this.addClickHandler(new MapCenterOnResult(result));
			this.addStyleDependentName("clickable");
		}
	}

	/**
	 * The class {@link MapCenterOnResult} allows centering the map when an object is clicked. The map is centered on
	 * the result which has been clicked.
	 * 
	 * @author thuguerre
	 * @since 1.1.0
	 */
	private class MapCenterOnResult implements ClickHandler {

		private TMapPoint result = null;

		/**
		 * Default constructor.
		 * 
		 * @param result
		 *            The result on which centering the map if clicked.
		 */
		public MapCenterOnResult(TMapPoint result) {
			this.result = result;
		}

		/**
		 * {@inheritDoc}
		 */
		@Override
		public void onClick(ClickEvent event) {
			MyMapWidget.getInstance().setCenter(result.getLatitude(), result.getLongitude());
		}
	}
}
